#ifndef LOGHANDLER_H
#define LOGHANDLER_H

#include <QDebug>
#include <QString>
#include <QDateTime>
#include <stdio.h>
#include <stdlib.h>

#include "colors.h"

namespace LogHandler {

enum class LogMode {
    Normal,
    Debug,
};
enum class LogFormat {
    NoFileInfo,
    WithFileInfo,
};

LogMode g_mode = LogMode::Normal;
LogFormat g_format = LogFormat::NoFileInfo;

#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
void MessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    QDateTime datetime = QDateTime::currentDateTime();
    QString date = datetime.date().toString("yyyy.MM.dd");
    QString time = datetime.time().toString("hh:mm:ss");
    QString file = context.file ? context.file : "??";
    QString line = QString::number(context.line);
    QString function = context.function ? context.function : "????";
    QByteArray locale_message = msg.toUtf8();

    // [FLAG] DATE TIME - MSG
    QString prefix = QString("%1 %2").arg(date, time);
    // [FLAG] DATE TIME [FILE:LINE, FUNCTION] - MSG
    if (g_format == LogFormat::WithFileInfo) {
        // prefix = prefix.append(QString("%1 %2 [" C_LB "%3" C_CL ":%4 - " C_LY "%5" C_CL "]").arg(date, time, file, line, function));
        QString finfo = "";
        if (!file.isEmpty() && !line.isEmpty()) {
            if (function.isEmpty()) {
                finfo = finfo.append(QString("[" C_LB "%1" C_CL ":%2]").arg(file, line));
            } else {
                finfo = finfo.append(QString("[" C_LB "%1" C_CL ":%2 - " C_LY "%3" C_CL "]").arg(file, line, function));
            }
        }
        if (!finfo.isEmpty()) {
            prefix = prefix.append(QString(" %1").arg(finfo));
        }
    }

    QString message = locale_message;
    QString p_message = "";
    if (locale_message.startsWith(C_LP "[")) {
        int index = message.indexOf("]" C_CL) + QString("]" C_CL).length();
        p_message = message.left(index);
        if (p_message.contains(" - ")) {
            message = locale_message.mid(index).trimmed();
        }
    }

    FILE *channel = stderr;
    QString p_type = "";
    QString s_message = "";
    QString output = "";
    switch (type)
    {
    case QtDebugMsg:
        if (g_mode == LogMode::Debug) {
            p_type = "[" C_CL "D" C_CL "]";
            s_message = QString(C_CL "%1" C_CL).arg(message);
        }
        break;
    case QtInfoMsg:
        if (g_mode != LogMode::Debug) {
            channel = stdout;
        }
        p_type = "[" C_HL "I" C_CL "]";
        s_message = QString(C_HL "%1" C_CL).arg(message);
        break;
    case QtWarningMsg:
        p_type = "[" C_HY "W" C_CL "]";
        s_message = QString(C_HY "%1" C_CL).arg(message);
        break;
    case QtCriticalMsg:
        p_type = "[" C_HR "E" C_CL "]";
        s_message = QString(C_HR "%1" C_CL).arg(message);
        break;
    case QtFatalMsg:
        p_type = "[" C_HR "F" C_CL "]";
        s_message = QString(C_HR "%1" C_CL).arg(message);
        break;
    }
    if (!s_message.isEmpty()) {
        if (p_message.isEmpty()) {
            output.append(QString("%1 %2 - %3").arg(p_type, prefix, s_message));
        } else {
            output.append(QString("%1 %2 - %3 %4").arg(p_type, prefix, p_message, s_message));
        }
        fprintf(channel, "%s\n", output.toLocal8Bit().constData());
    }
}
#endif // QT_VERSION_CHECK

// 在 main 函数中开头位置调用
void InstallLogHandler(LogMode mode = LogMode::Normal, LogFormat format = LogFormat::NoFileInfo)
{
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
    qInstallMessageHandler(MessageHandler);
    g_mode = mode;
    g_format = format;
#endif
}

void SetLogMode(LogMode mode)
{
    g_mode = mode;
}

void SetLogFormat(LogFormat format)
{
    g_format = format;
}

} // namespace LogHandler

#endif // LOGHANDLER_H
